/*********************************
*-- 33 KDH Knieja ---------------*
*-- im. Harcerzy Września 1939 --*
*-- autor: Marcin Rzepisko ------*
*-- data: 2014-03-18 ------------*
**********************************/

package net.kdh.knieja.kontroler.narzedzia;

import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.Interceptors;
import javax.interceptor.InvocationContext;
import net.kdh.knieja.dao.interfejsy.ObslugaUzytkownikowDAO;
import net.kdh.knieja.model.system.token.Token;
import net.kdh.knieja.model.system.token.TokenAdmina;
import net.kdh.knieja.model.system.token.TokenModa;
import net.kdh.knieja.model.system.token.TokenSuperUsera;
import net.kdh.knieja.model.wspolne.adnotacje.Uprawnienia;
import net.kdh.knieja.model.wspolne.enumeracje.TypKontaEnum;
import net.kdh.knieja.model.wspolne.wyjatki.BladAutoryzacjiWyjatek;
import net.kdh.knieja.model.wspolne.wyjatki.BladWalidacjiWyjatek;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author rz.marcin@gmail.com
 */
@Interceptor
@Interceptors(ZapisWyjatkowInterceptor.class)
public class KontrolaDostepuInterceptor {
    private final static Logger LOGGER = LoggerFactory.getLogger("Dostep");
    private final static Walidator walidator = new Walidator();

    @Inject
    private ObslugaUzytkownikowDAO obslugaUzytkownikowDAO;

    @AroundInvoke
    public void kontrolujUprawnienia(final InvocationContext context) throws Exception {
        Uprawnienia typUprawnien = context.getMethod().getAnnotation(Uprawnienia.class);
        if (typUprawnien != null && !typUprawnien.value().equals(TypKontaEnum.GST)) {
            boolean czyPrzekazanoToken = false;
            Token token;
            for (Object o : context.getParameters()) {
                if (o instanceof Token) {
                    czyPrzekazanoToken = true;
                    token = (Token) o;
                    LOGGER.info(
                            sprawdzToken(token, typUprawnien, context));
                    break;
                }
            }
            if (!czyPrzekazanoToken) {
                throw new BladAutoryzacjiWyjatek(
                        String.format("Brak tokenu bezpieczeństwa przy wywoływaniu usługi {0}.", context.getMethod().getName()));
            }
        }
        context.proceed();
    }

    private String sprawdzToken(final Token token, final Uprawnienia uprawnienia, final InvocationContext context) throws BladAutoryzacjiWyjatek, BladWalidacjiWyjatek {
        String brakDostepu = "Brak dostępu do usługi {0} dla użytkownika {1} na poziomie {2}.";

        switch (uprawnienia.value()) {
            case ADM: {
                if (!(token instanceof TokenAdmina)) {
                    throw new BladAutoryzacjiWyjatek(String.format(brakDostepu, context.getMethod().getName(), token.getLogin(), "Administrator"));
                }
                break;
            }
            case MOD: {
                if (!(token instanceof TokenModa)) {
                    throw new BladAutoryzacjiWyjatek(String.format(brakDostepu, context.getMethod().getName(), token.getLogin(), "Moderator"));
                }
                break;
            }
            case PWR: {
                if (!(token instanceof TokenSuperUsera)) {
                    throw new BladAutoryzacjiWyjatek(String.format(brakDostepu, context.getMethod().getName(), token.getLogin(), "Super User"));
                }
                break;
            }
            case USR: {
                if (!(token instanceof Token)) {
                    throw new BladAutoryzacjiWyjatek(String.format(brakDostepu, context.getMethod().getName(), token.getLogin(), "Użytkownik"));
                }
                break;
            }
        }
        try {
            walidator.weryfikujKlase(token);
        } catch (BladWalidacjiWyjatek ex) {
            LOGGER.error(String.format("\nNiepoprawny format tokena!\n\tUżytkownik: {0}\n\tID: {1}", 
                    token.getLogin(), token.getIdUzytkownika()));
            obslugaUzytkownikowDAO.usunToken(token);
            throw ex;
        }
        String dostep = "Udzielono dostępu do usługi {0} dla użytkownika {1}";
        return String.format(dostep, context.getMethod().getName(), token.getLogin());
    }
}
